package com.ruoyi.common.core.domain.tree;

import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 描述 树结构工具类
 * 作者 ZhangPing
 * 创建时间 2023/9/1 14:59
 */
public class TreeHelper {

    /**
     * 列表转树结构
     * @param list
     * @return
     */
    public static <T extends ITree<T>> List<T> buildTree(List<T> list) {
        if (list == null || list.size() == 0) return Collections.emptyList();
        // 根节点
        List<T> topNodes = new ArrayList<>();
        Map<String, T> treeMap = new HashMap<>();
        for (T node : list) {
            // 把所有的节点放到map当中，id为key
            treeMap.put(node.id(), node);
            // 没有找到父节点，则当前节点为顶级节点
            if (findParentNode(list, node) == null) {
                topNodes.add(node);
            }
        }
        // 把子节点放到父节点的children中
        for (T node : list) {
            T parentNode = findParentNode(list, node);
            if (parentNode != null){
                //将子节点放入父节点
                node.parentId(parentNode.id());
                parentNode.getChildren().add(node);
            }
        }
        return topNodes;
    }

    /**
     * 寻找最相近的父节点
     * @param list
     * @param node
     * @param <T>
     * @return
     */
    private static <T extends ITree<T>> T findParentNode(List<T> list, T node){
        List<String> ancestors = StringUtils.isEmpty(node.ancestors()) ? new ArrayList<>() : Arrays.asList(node.ancestors().split(","));
        if (CollectionUtils.isEmpty(ancestors)) ancestors = Collections.singletonList(node.parentId());
        Map<String, T> treeMap = list.stream().collect(Collectors.toMap((ITree i) -> i.id(), Function.identity()));
        for (int i = ancestors.size() - 1; i >= 0; i--) {
            String parentId = ancestors.get(i);
            if (treeMap.keySet().contains(parentId)){
               return treeMap.get(parentId);
            }
        }
        return null;
    }

    /**
     * 树结构转成列表结构
     * @param nodeList
     * @return
     */
    public static <T extends ITree<T>> List<T> treeToList(List<T> nodeList){
        List<T> resultList = new ArrayList<>();
        nodeList.stream().forEach(node -> depthAddTree(resultList, node));
        return resultList;
    }

    private static <T extends ITree<T>> void depthAddTree(List<T> resultList, T node){
        resultList.add(node);
        for (T child : node.getChildren()) {
            depthAddTree(resultList, child);
            node.childrenToEmpty();
        }
    }

    /**
     * 列表转换树结构（确认子节点的父节点一定存在，不重组爷孙关系）
     * @param list
     * @param <T>
     * @return
     */
    public static <T extends ITree<T>> List<T> buildTreeHasParent(List<T> list) {
        if (list == null || list.size() == 0) return Collections.emptyList();
        // 根节点
        List<T> topNodes = new ArrayList<>();
        Map<String, T> treeMap = new HashMap<>();
        for (T node : list) {
            // 把所有的节点放到map当中，id为key
            treeMap.put(node.id(), node);
        }
        // 把子节点放到父节点的children中
        for (T node : list) {
            T parentNode = treeMap.get(node.parentId());
            if (parentNode != null){
                //将子节点放入父节点
                parentNode.getChildren().add(node);
            } else { // 没有父节点，就设为顶级节点
                topNodes.add(node);
            }
        }
        return topNodes;
    }
}
